/**
 * 
 */
package br.org.bertol.mestrado.engine.fitness;

import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;

import br.org.bertol.mestrado.engine.Objective;
import br.org.bertol.mestrado.engine.optimisation.entity.AbstractUnit;
import br.org.bertol.mestrado.engine.optimisation.moo.ParetoMinMaxDominace;

/**
 * @author contaqualquer
 */
public class MutantAnalysis extends AbstractCombinatorialFitness<String> {

    /**
     * Fronteira de Pareto.
     */
    private transient ParetoMinMaxDominace paretoDominace = new ParetoMinMaxDominace();

    /**
     * Teste case selecionados.
     */
    private transient List<String>         testCase       = new ArrayList<String>();

    public MutantAnalysis(final ArrayList<String> classes) {
        super(classes);
    }

    @Override
    public final boolean fitness(final List<String> route,
            final EnumMap<Objective, Number> height) {

        for (final Objective objective : height.keySet()) {

            switch (objective) {

                case MUTANTES:
                    height.put(objective, objective.getConstraintHeight(route));

                    testCase = objective.getInfo();

                    break;
                case COBERTURA:
                    height.put(objective, objective
                            .getConstraintHeight(testCase));

                    break;
                default:
                    break;
            }
        }
        return true;
    }

    @SuppressWarnings("unchecked")
    @Override
    public final Object clone() throws CloneNotSupportedException {

        final MutantAnalysis tmp = (MutantAnalysis) super.clone();

        tmp.testCase = (List<String>) ((ArrayList<String>) this.testCase)
                .clone();

        return tmp;
    }

    @Override
    public final void reset() {
        testCase.clear();
    }

    @Override
    public final boolean stopCriteria() {
        return false;
    }

    @SuppressWarnings("unchecked")
    @Override
    public final <U extends AbstractUnit<String>> U doBetter(final U unit)
            throws Exception {

        final U tmp = (U) unit.clone();

        final ArrayList<String> reducedClasses = (ArrayList<String>) classes
                .clone();

        reducedClasses.removeAll(unit.getRoute());

        // realiza a troca por um outro operador
        for (final String operador : unit.getRoute()) {

            tmp.removeClass(operador);

            tmp.calcFitness();

            if (paretoDominace
                    .compare(tmp.getHeight(), unit.getHeight()) != ParetoMinMaxDominace.LEFT_DOMINE) {
                tmp.addClass(operador);

                tmp.calcFitness();
            }

        }

        return tmp;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final String toString() {
        final StringBuilder buffer = new StringBuilder();

        buffer.append("Casos de teste : ").append(testCase.toString());

        return buffer.toString();
    }

}
